/*
 * @Description:
 * @Author: maxyang
 * @Date: 2022-05-25 21:18:28
 * @LastEditTime: 2022-08-10 17:05:36
 * @LastEditors: liutq
 * @Reference:
 */
package user

import (
	"errors"
	"fmt"
	"time"

	"github.com/maxyang107/jinglan/common"
	"github.com/maxyang107/jinglan/model"
	"github.com/maxyang107/jinglan/model/goods"
)

type MyCollect struct {
	ID              uint       `gorm:"column:id; parimary_key" json:"id"`
	OwnerUid        uint       `gorm:"column:owner_uid" json:"owner_uid" `
	HistoryOwner    uint       `gorm:"column:history_owner" json:"history_owner" `
	GoodsKind       uint8      `gorm:"column:goods_kind" json:"goods_kind" `
	GoodsId         uint       `gorm:"column:goods_id" json:"goods_id" `
	GoodsCode       string     `gorm:"column:goods_code" json:"goods_code" `
	CertificatId    string     `gorm:"column:certificat_id" json:"certificat_id" `
	CertificatHash  string     `gorm:"column:certificat_hash" json:"certificat_hash" `
	CertificatTiime time.Time  `gorm:"column:certificat_tiime" json:"certificat_tiime" `
	BlockHeight     uint       `gorm:"column:block_height" json:"block_height" `
	CollectTime     time.Time  `gorm:"column:collect_time" json:"collect_time" `
	CollectType     uint8      `gorm:"column:collect_type" json:"collect_type" `
	CreateTime      time.Time  `gorm:"column:create_time" json:"create_time" `
	IsOpen          uint8      `gorm:"column:is_open" json:"is_open" `
	DeleteTag       uint8      `gorm:"column:delete_tag" json:"delete_tag" `
	GoodsType       uint8      `gorm:"column:goods_type" json:"goods_type" `
	RepoStatus      uint8      `gorm:"column:repo_status" json:"repo_status" `
	RepoStartTime   *time.Time `gorm:"column:repo_start_time" json:"repo_start_time" `
	SmsNotice       uint8      `gorm:"column:sms_notice" json:"sms_notice" `
	SerialNumber    string     `gorm:"column:serial_number" json:"serial_number" `
	PayStatus       uint8      `gorm:"column:pay_status" json:"pay_status" `
	PayTime         time.Time  `gorm:"column:pay_time" json:"pay_time" `
	OrderNo         string     `gorm:"column:order_no" json:"order_no" `
}

type MyCollectTmp struct {
	ID             uint   `gorm:"column:id; parimary_key" json:"id"`
	GoodsId        uint   `gorm:"column:goods_id" json:"goods_id"`
	GoodsNum       uint   `gorm:"column:goods_num" json:"goods_num"`
	GoodsName      string `gorm:"column:goods_name" json:"goods_name"`
	GoodsListImg   string `gorm:"column:goods_list_img" json:"goods_list_img"`
	GoodsCode      string `gorm:"column:goods_code" json:"goods_code"`
	GoodsBlindCode string `gorm:"column:goods_blind_code" json:"goods_blind_code" `
}

type MyCollectDetail struct {
	ID              uint      `gorm:"column:id; parimary_key" json:"id"`
	GoodsId         uint      `gorm:"column:goods_id" json:"goods_id"`
	GoodsNum        uint      `gorm:"column:goods_num" json:"goods_num"`
	GoodsName       string    `gorm:"column:goods_name" json:"goods_name"`
	GoodsListImg    string    `gorm:"column:goods_list_img" json:"goods_list_img"`
	GoodsCode       string    `gorm:"column:goods_code" json:"goods_code"`
	GoodsIssuer     string    `gorm:"column:goods_issuer" json:"goods_issuer"`
	GoodsAuthorized string    `gorm:"column:goods_authorized" json:"goods_authorized"`
	OwnerUid        uint      `gorm:"column:owner_uid" json:"owner_uid" `
	Headimg         string    `gorm:"column:headimg" json:"headimg" `
	CertificatId    string    `gorm:"column:certificat_id" json:"certificat_id" `
	CertificatHash  string    `gorm:"column:certificat_hash" json:"certificat_hash" `
	CertificatTiime time.Time `gorm:"column:certificat_tiime" json:"certificat_tiime" `
	BlockHeight     uint      `gorm:"column:block_height" json:"block_height" `
	CollectTime     time.Time `gorm:"column:collect_time" json:"collect_time" `
	GoodsType       uint8     `gorm:"column:goods_type" json:"goods_type" `
	RepoStatus      uint8     `gorm:"column:repo_status" json:"repo_status" `
	RepoStartTime   time.Time `gorm:"column:repo_start_time" json:"repo_start_time" `
	GoodsRepoPrice  float64   `gorm:"column:goods_repo_price" json:"goods_repo_price"`
}

type CollectList struct {
	Page    int
	PerPage int
	Total   int
	Data    []MyCollectTmp
}

func GetUserCollectList(query_ common.PramCollect) *CollectList {
	var CollectList_ CollectList

	CollectList_.Page = query_.Page
	CollectList_.PerPage = query_.PerPage
	where_ := buildWhere(query_.UserId, uint8(query_.Kind), query_.Id)
	CollectList_.Total = getCollectTotal(query_.PerPage, where_)

	if query_.Id > 0 {
		model.Db.Table("my_collect").Select("my_collect.id, my_collect.goods_id, my_collect.goods_code , goods.goods_name,goods.goods_list_img,goods.goods_blind_code").Joins("left join goods on goods.id=my_collect.goods_id").Where(where_).Scan(&CollectList_.Data)
	} else {
		model.Db.Table("my_collect").Select("ANY_VALUE(my_collect.id) as id, my_collect.goods_id, ANY_VALUE(my_collect.goods_code) as goods_code ,count(my_collect.goods_id) as goods_num, goods.goods_name,goods.goods_list_img,goods.goods_blind_code").Joins("left join goods on goods.id=my_collect.goods_id").Where(where_).Group("my_collect.goods_id").Scan(&CollectList_.Data)
	}

	return &CollectList_
}

func getCollectTotal(perpage int, where_ *MyCollect) int {
	var total int
	if where_.GoodsId > 0 {
		model.Db.Model(&MyCollect{}).Where(where_).Count(&total)
	} else {
		model.Db.Model(&MyCollect{}).Where(where_).Group("goods_id").Count(&total)
	}
	pageNum := total / perpage
	if total%perpage != 0 {
		pageNum++
	}

	return pageNum
}

func buildWhere(userId uint, goodsKind uint8, goodsId uint) *MyCollect {
	var where MyCollect
	if goodsId > 0 {
		where = MyCollect{GoodsKind: goodsKind, GoodsId: goodsId, OwnerUid: userId, DeleteTag: 0}
	} else {
		where = MyCollect{GoodsKind: goodsKind, OwnerUid: userId, DeleteTag: 0}
	}
	return &where
}

func SaveMyCollect(mycollect_ *MyCollect) (uint, error) {
	err := model.Db.Create(&mycollect_).Error
	if err != nil {
		return 0, err
	}
	return mycollect_.ID, nil
}

func GetCurrleGoodsCode(goodsId uint, collectId_ uint) uint {

	var total uint
	model.Db.Model(&MyCollect{}).Where("id <= ?", collectId_).Where("goods_id = ?", goodsId).Where("goods_kind = ?", 1).Where("delete_tag = ?", 0).Count(&total)
	return total
}

func UpdateMyCollect(mycollect_ *MyCollect) error {
	if err := model.Db.Model(&MyCollect{}).Update(&mycollect_).Error; err != nil {
		return err
	}
	return nil
}

func GetUserCollectById(userId_ uint, id_ uint) *MyCollect {
	var mycollect_ MyCollect

	model.Db.Where(&MyCollect{OwnerUid: userId_, ID: id_, DeleteTag: 0}).First(&mycollect_)
	return &mycollect_
}

func GetUserCollectByGoodsId(userId_ uint, goodsId_ uint) *MyCollect {
	var mycollect_ MyCollect

	model.Db.Where(&MyCollect{OwnerUid: userId_, GoodsId: goodsId_, DeleteTag: 0}).First(&mycollect_)
	return &mycollect_
}

func GetUserCollectDetailById(userId_ uint, id_ uint) *MyCollectDetail {
	var mycollect MyCollectDetail

	model.Db.Table("my_collect").Select("my_collect.*,user.username,user.headimg, goods.goods_name,goods.goods_list_img,goods.goods_repo_price,goods.goods_issuer,goods.goods_authorized").Joins("inner join goods on goods.id=my_collect.goods_id").Joins("inner join user on user.id = my_collect.owner_uid").Where(&MyCollect{ID: id_, OwnerUid: userId_, GoodsKind: 1, DeleteTag: 0}).Find(&mycollect)
	fmt.Println(mycollect)
	return &mycollect
}

func Buildcollect(goodsInfo *goods.GoodsTmp, userId_ uint, collecttype_ uint8, orderNo string, kind uint8, paystatus uint8) error {
	//获取链上信息
	chainInfo_ := goods.GetChainInfo(goodsInfo.ID)
	if chainInfo_.GoodsId == 0 {
		return errors.New("没有找到链上信息")
	}
	var mycollect MyCollect
	mycollect.OwnerUid = userId_
	mycollect.GoodsKind = kind
	mycollect.GoodsId = goodsInfo.ID
	mycollect.BlockHeight = chainInfo_.BlockHeight
	mycollect.CertificatHash = chainInfo_.CertificatHash
	mycollect.CertificatId = chainInfo_.CertificatId
	mycollect.CertificatTiime = chainInfo_.CertificatTiime
	mycollect.CollectTime = time.Now()
	mycollect.CollectType = collecttype_
	mycollect.OrderNo = orderNo
	mycollect.CreateTime = time.Now()
	mycollect.DeleteTag = 0
	mycollect.PayStatus = paystatus
	if goodsInfo.GoodsKind == 3 {
		mycollect.GoodsType = 1
	}

	collectId_, err := SaveMyCollect(&mycollect)

	if err != nil {
		return err
	}

	u2 := GetCurrleGoodsCode(goodsInfo.ID, collectId_)

	s := fmt.Sprintf("%d/%d", u2, goodsInfo.GoodsCirculation)

	mycollect.GoodsCode = s

	if err := UpdateMyCollect(&mycollect); err != nil {
		return err
	}
	addLuckyNum(userId_, goodsInfo.LuckyNum)
	return nil
}

func CheckCollectExist(orderid_ string, userid uint) bool {
	var tmp MyCollect

	model.Db.Where(&MyCollect{SerialNumber: orderid_, OwnerUid: userid, DeleteTag: 0}).First(&tmp)

	return tmp.ID > 0
}

func GetDrawCollect(goodsid uint, userid uint) int {
	var num int
	model.Db.Table("my_collect").Where("goods_id = ?", goodsid).Where("owner_uid = ?", userid).Count(&num)
	return num
}

func ModifyOrder(userId int, orderno string, serial_number string) error {
	var tmp MyCollect

	model.Db.Model(&MyCollect{}).Where("owner_uid = ?", userId).Where("order_no = ?", orderno).First(&tmp)

	if tmp.ID == 0 {
		return errors.New("没有找到订单信息")
	}

	tmp.PayStatus = 1
	tmp.PayTime = time.Now()
	tmp.SerialNumber = serial_number

	if err := model.Db.Model(&MyCollect{}).Update(&tmp).Error; err != nil {
		return err
	}
	return nil
}

func RmExpertimeOrder(orderNo string) error {
	tx := model.Db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	var tmp MyCollect
	model.Db.Model(&MyCollect{}).Where("order_no = ?", orderNo).First(&tmp)
	if tmp.ID == 0 {
		return nil
	}

	var gtmp goods.Goods
	model.Db.Model(&goods.Goods{}).Where("id = ?", tmp.GoodsId).First(&gtmp)

	if gtmp.ID > 0 {
		gtmp.GoodsStore = gtmp.GoodsStore + 1
		if err := tx.Model(&goods.Goods{}).Update(&gtmp).Error; err != nil {
			tx.Rollback()
			return errors.New("库存恢复失败")
		}
	}
	if err := tx.Model(&MyCollect{}).Delete(&tmp).Error; err != nil {
		tx.Rollback()
		return errors.New("订单删除失败")
	}
	return tx.Commit().Error
}

func GetMyCollectByGoodsIdAndUserId(goodsId uint, userId uint) bool {
	var tmp MyCollect
	model.Db.Model(&MyCollect{}).Where("goods_id = ? and owner_uid = ?", goodsId, userId).First(&tmp)
	return tmp.ID > 0
}
